package org.six11.olive3.server;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static org.six11.olive3.server.WebActionServlet.*;

import javax.servlet.ServletException;

/**
 * 
 * 
 * @author Gabe Johnson <johnsogg@cmu.edu>
 */
public class DrillData {

  public static final String TYPE_SKETCH = "sketch";
  public static final String TYPE_DESC = "desc";
  public static String DEFAULT_IMAGE_DIR = "img";
  public static int THUMB_SIZE = 120;

  private String type;
  private static NumberFormat formatter = new DecimalFormat("#.#");

  public String getType() {
    return type;
  }

  public void setType(String type) {
    this.type = type;
  }

  public String getId() {
    return id;
  }

  public void setId(String id) {
    this.id = id;
  }

  public String getAveRating() {
    return aveRating;
  }

  public void setAveRating(String aveRating) {
    this.aveRating = aveRating;
  }

  public String getNumRatings() {
    return numRatings;
  }

  public void setNumRatings(String numRatings) {
    this.numRatings = numRatings;
  }

  public String getParentID() {
    return parentID;
  }

  public void setParentID(String parentID) {
    this.parentID = parentID;
  }

  public String getText() {
    return text;
  }

  public void setText(String text) {
    this.text = text;
  }

  private String id;
  private String aveRating;
  private String numRatings;
  private String parentID;
  private String text;

  public String getPdfUrl(String imgDir) {
    return imgDir + "/" + id + ".pdf";
  }

  public String getPdfUrl() {
    return getPdfUrl(DEFAULT_IMAGE_DIR);
  }

  public String getSmallPngUrl() {
    return DEFAULT_IMAGE_DIR + "/" + id + "-" + THUMB_SIZE + ".png";
  }

  public String getPenUrl() {
    return "penData?" + PARAM_SKETCH_ID +"=" + id;
  }
  
  public String getPngUrl(String imgDir) {
    return imgDir + "/" + id + ".png";
  }

  public String getPngUrl() {
    return getPngUrl(DEFAULT_IMAGE_DIR);
  }

  public static List<DrillData> getLineage(DatabaseThing db, String type, String id)
      throws ServletException {
    List<DrillData> ret = new ArrayList<DrillData>();
    if (type.equals(TYPE_SKETCH)) {
      addLineageSketch(db, id, ret);
    } else {
      addLineageDesc(db, id, ret);
    }
    return ret;
  }

  private static void addLineageSketch(DatabaseThing db, String id, List<DrillData> ret)
      throws ServletException {
    // 'id' is a sketch. collect all the data we need about it.
    DrillData addMe = getDrillData(db, TYPE_SKETCH, id);
    if (addMe.parentID != null) {
      addLineageDesc(db, addMe.parentID, ret);
    }
    ret.add(addMe);
  }

  public static DrillData getDrillData(DatabaseThing db, String type, String id)
      throws ServletException {
    DrillData ret = new DrillData();
    if (type.equals(TYPE_DESC)) {
      ret.type = TYPE_DESC;
      ret.id = id;
      Map<String, String> val = db.getRow(SqlStrings.FIND_DESCRIPTION, id);
      ret.text = val.get("text");
      ret.parentID = val.get("sketch_id");
    } else {
      ret.type = TYPE_SKETCH;
      ret.id = id;
      List<String> info = db.getRowAsList(SqlStrings.FIND_RATING_FOR_SKETCH, id);
      if (info.get(0) == null) {
        ret.aveRating = "?";
      } else {
        ret.aveRating = formatter.format(Double.parseDouble(info.get(0)));
      }
      ret.numRatings = info.get(1);
      Map<String, String> val = db.getRow(SqlStrings.FIND_SKETCH_PARENT, id);
      ret.parentID = val.get("description_id");
    }
    return ret;
  }

  private static void addLineageDesc(DatabaseThing db, String id, List<DrillData> ret)
      throws ServletException {
    // 'id' is a description
    DrillData addMe = getDrillData(db, TYPE_DESC, id);
    if (addMe.parentID != null) {
      addLineageSketch(db, addMe.parentID, ret);
    }
    ret.add(addMe);
  }

  public String toString() {
    return "type: " + type + ", id: " + id + ", aveRating: " + aveRating + ", numRatings: "
        + numRatings + ", parentID: " + parentID + ", text: " + text;
  }

  /**
   * Finds the (potentially empty) list of child nodes.
   */
  public static List<DrillData> getLeaves(DatabaseThing dbThing, String type, String targetID)
      throws ServletException {
    List<DrillData> ret = new ArrayList<DrillData>();
    String childType = type == TYPE_DESC ? TYPE_SKETCH : TYPE_DESC;
    String idQuery = type == TYPE_DESC ? SqlStrings.FIND_DESCRIPTION_CHILDREN
        : SqlStrings.FIND_SKETCH_CHILDREN;
    List<Integer> childIDs = dbThing.getIDs(idQuery, targetID);
    for (int id : childIDs) {
      ret.add(getDrillData(dbThing, childType, "" + id));
    }
    return ret;
  }

  public static List<DrillData> getRecentSketches(DatabaseThing dbThing) throws ServletException {
    List<DrillData> ret = new ArrayList<DrillData>();
    List<Integer> ids = dbThing.getIDs(SqlStrings.FIND_RECENT_SKETCHES, new String[] { });
    for (int id : ids ) {
      ret.add(getDrillData(dbThing, TYPE_SKETCH, "" + id));
    }
    return ret;
  }

  public static List<DrillData> getPeruse(DatabaseThing dbThing) throws ServletException {
    List<DrillData> everything = new ArrayList<DrillData>();
    List<Integer> allSketches = dbThing.getIDs(SqlStrings.FIND_SKETCHES, new String[] {});
    for (int id : allSketches) {
      everything.add(getDrillData(dbThing, TYPE_SKETCH, "" + id));
    }
    return everything;
  }
}
